/*
 * Wazuh Vulnerability scanner - Scan Orchestrator
 * Copyright (C) 2015, Wazuh Inc.
 * March 25, 2023.
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public
 * License (version 2) as published by the FSF - Free Software
 * Foundation.
 */

#ifndef _SCAN_CONTEXT_HPP
#define _SCAN_CONTEXT_HPP

#include "external/nlohmann/json.hpp"
#include "flatbuffers/include/rsync_generated.h"
#include "flatbuffers/include/syscollector_deltas_generated.h"
#include "globalData.hpp"
#include "logging_helper.h"
#include "osDataCache.hpp"
#include "remediationDataCache.hpp"
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <variant>
#include <vector>

enum VulnerabilitySource
{
    ADP_BASE = 0,
    ADP_EXPANDED = 1
};

enum class MessageType
{
    Unknown = 0,
    Delta = 1,
    Sync = 2,
    ActionTrigger = 3,
    DataJSON = 4,
};

enum class ScannerType
{
    Unknown = 0,
    PackageInsert = 1,
    PackageDelete = 2,
    Os = 3,
    HotfixInsert = 4,
    HotfixDelete = 5,
    IntegrityClear = 6,
    ReScanAllAgents = 7,
    ReScanSingleAgent = 8,
    CleanupAllAgentData = 9,
    CleanupSingleAgentData = 10,
    GlobalSyncInventory = 11
};

// The affected component type is used to determine what type of data is affected in the system.
enum class AffectedComponentType
{
    Unknown = 0,
    Package = 1,
    Os = 2,
    Hotfix = 3,
    Agent = 4,
};

// Match rule condition.
enum class MatchRuleCondition
{
    Unknown = 0,
    Equal = 1,
    NotEqual = 2,
    GreaterThan = 3,
    GreaterThanOrEqual = 4,
    LessThan = 5,
    LessThanOrEqual = 6,
    Contains = 7,
    NotContains = 8,
    StartsWith = 9,
    EndsWith = 10,
    DefaultStatus = 11,
};

// Element operation delete or insert.
enum class ElementOperation
{
    Unknown = 0,
    Delete = 1,
    Insert = 2,
};

// Wazuh-DB upgrade schema versions handling
enum WazuhDBUpgradeSchemaVersion
{
    V15 = 15
};

/**
 * @brief MatchCondition structure.
 */
struct MatchCondition
{
    std::string version;          ///< Version.
    MatchRuleCondition condition; ///< Condition.
};

/**
 * @brief Agent data structure.
 */
struct AgentData
{
    std::string id;      ///< Agent ID.
    std::string name;    ///< Agent name.
    std::string version; ///< Agent version.
    std::string ip;      ///< Agent IP.
};

/**
 * @brief ScanContext structure.
 *
 * @tparam TOsDataCache os data cache type.
 * @tparam TGlobalData global data type.
 * @tparam TRemediationDataCache remediation data cache type.
 */
template<typename TOsDataCache = OsDataCache<>,
         typename TGlobalData = GlobalData,
         typename TRemediationDataCache = RemediationDataCache<>>
struct TScanContext final
{
private:
    /**
     * @brief Extracts and processes data from different message types.
     *
     * The `extractData` function extracts and processes data from various message types using provided functions.
     *
     * @tparam T The return type of the extraction and processing functions.
     * @param sysDeltaFunc A function to extract and process data from SyscollectorDeltas::Delta messages.
     * @param sysSyncFunc A function to extract and process data from Synchronization::SyncMsg messages.
     * @param jsonFunc A function to extract and process data from nlohmann::json messages (defaulted to return a
     * default-constructed T).
     * @return The extracted and processed data of type T.
     *
     * @note This function handles different message types and applies the appropriate extraction and processing
     * function. It returns the result of the extraction and processing, or a default-constructed T if the message type
     * is not a JSON query or action type. It may throw a std::runtime_error if the message type is unknown.
     */
    template<typename T>
    T extractData(
        std::function<T(const SyscollectorDeltas::Delta*)> sysDeltaFunc,
        std::function<T(const Synchronization::SyncMsg*)> sysSyncFunc,
        std::function<T(const nlohmann::json*)> jsonFunc = [](const nlohmann::json*) -> T { return T(); }) const
    {
        if (m_messageType == MessageType::Delta)
        {
            auto delta = std::get<const SyscollectorDeltas::Delta*>(m_data);
            return sysDeltaFunc(delta);
        }
        else if (m_messageType == MessageType::Sync)
        {
            auto syncMsg = std::get<const Synchronization::SyncMsg*>(m_data);
            return sysSyncFunc(syncMsg);
        }
        else if (m_messageType == MessageType::DataJSON)
        {
            auto json = std::get<const nlohmann::json*>(m_data);
            return jsonFunc(json);
        }
        else if (m_messageType == MessageType::ActionTrigger)
        {
            return T();
        }
        else
        {
            throw std::runtime_error("Unable to extract data from message. Unknown type");
        }
    }

    /**
     * @brief Build CPE name.
     */
    void buildCPEName()
    {
        const auto& osCpeMaps = TGlobalData::instance().osCpeMaps();

        m_osData.cpeName = "cpe:/o:";

        std::string cpe;
        for (auto it = osCpeMaps.rbegin(); it != osCpeMaps.rend(); ++it)
        {
            if (m_osData.name.compare(it.key()) == 0 || Utils::startsWith(m_osData.name, it.key()) ||
                m_osData.platform.compare(it.key()) == 0)
            {
                cpe = it.value();
                break;
            }
        }

        if (!cpe.empty())
        {
            // Replace variables in the CPE name
            Utils::replaceAll(cpe, "$(MAJOR_VERSION)", m_osData.majorVersion);
            Utils::replaceAll(cpe, "$(MINOR_VERSION)", m_osData.minorVersion);
            Utils::replaceAll(cpe, "$(DISPLAY_VERSION)", m_osData.displayVersion);
            Utils::replaceAll(cpe, "$(VERSION)", m_osData.version);
            Utils::replaceAll(cpe, "$(RELEASE)", m_osData.release);

            // For SUSE, replace the hyphen in the version with a colon, because inner the version we have the version
            // update.
            auto versionWithHyphen {m_osData.version};
            Utils::replaceAll(versionWithHyphen, "-", ":");
            Utils::replaceAll(cpe, "$(VERSION_UPDATE_HYPHEN)", versionWithHyphen);

            m_osData.cpeName += Utils::toLowerCase(cpe);
        }
        else
        {
            // Clear the cpeName if the OS is not supported
            m_osData.cpeName = "";
        }
    }

public:
    // LCOV_EXCL_START
    /**
     * @brief Class constructor.
     *
     */
    TScanContext() = default;
    // LCOV_EXCL_STOP

    /**
     * @brief Class constructor.
     *
     * @param data Scan context.
     */
    explicit TScanContext(
        std::variant<const SyscollectorDeltas::Delta*, const Synchronization::SyncMsg*, const nlohmann::json*> data)
    {
        std::visit(
            [this](auto&& arg)
            {
                using T = std::decay_t<decltype(arg)>;
                if constexpr (std::is_same_v<T, const SyscollectorDeltas::Delta*>)
                {
                    m_data = arg;
                    m_messageType = MessageType::Delta;
                    auto delta = std::get<const SyscollectorDeltas::Delta*>(m_data);

                    if (delta->operation())
                    {
                        if (delta->data_type() == SyscollectorDeltas::Provider_dbsync_packages)
                        {
                            // Set the affected component type
                            m_affectedComponentType = AffectedComponentType::Package;

                            // Modify events not exist for packages, because all fields that change in an update are PK.
                            if (delta->operation()->str().compare("INSERTED") == 0)
                            {
                                m_type = ScannerType::PackageInsert;
                            }
                            else if (delta->operation()->str().compare("DELETED") == 0)
                            {
                                m_type = ScannerType::PackageDelete;
                            }

                            // If data comes from Wdb, we build the CPE and update the cache
                            if (!TOsDataCache::instance().getOsData(agentId().data(), m_osData))
                            {
                                buildCPEName();
                                TOsDataCache::instance().setOsData(agentId().data(), m_osData);
                            }
                        }
                        else if (delta->data_type() == SyscollectorDeltas::Provider_dbsync_osinfo)
                        {
                            m_type = ScannerType::Os;

                            // Set the affected component type
                            m_affectedComponentType = AffectedComponentType::Os;

                            m_osData.architecture = delta->data_as_dbsync_osinfo()->architecture()
                                                        ? delta->data_as_dbsync_osinfo()->architecture()->str()
                                                        : "";
                            m_osData.name = delta->data_as_dbsync_osinfo()->os_name()
                                                ? delta->data_as_dbsync_osinfo()->os_name()->str()
                                                : "";
                            m_osData.version = delta->data_as_dbsync_osinfo()->os_version()
                                                   ? delta->data_as_dbsync_osinfo()->os_version()->str()
                                                   : "";
                            m_osData.codeName = delta->data_as_dbsync_osinfo()->os_codename()
                                                    ? delta->data_as_dbsync_osinfo()->os_codename()->str()
                                                    : "";
                            m_osData.majorVersion = delta->data_as_dbsync_osinfo()->os_major()
                                                        ? delta->data_as_dbsync_osinfo()->os_major()->str()
                                                        : "";
                            m_osData.minorVersion = delta->data_as_dbsync_osinfo()->os_minor()
                                                        ? delta->data_as_dbsync_osinfo()->os_minor()->str()
                                                        : "";
                            m_osData.patch = delta->data_as_dbsync_osinfo()->os_patch()
                                                 ? delta->data_as_dbsync_osinfo()->os_patch()->str()
                                                 : "";
                            m_osData.build = delta->data_as_dbsync_osinfo()->os_build()
                                                 ? delta->data_as_dbsync_osinfo()->os_build()->str()
                                                 : "";
                            m_osData.platform = delta->data_as_dbsync_osinfo()->os_platform()
                                                    ? delta->data_as_dbsync_osinfo()->os_platform()->str()
                                                    : "";
                            m_osData.release = delta->data_as_dbsync_osinfo()->os_release()
                                                   ? delta->data_as_dbsync_osinfo()->os_release()->str()
                                                   : "";
                            m_osData.displayVersion = delta->data_as_dbsync_osinfo()->os_display_version()
                                                          ? delta->data_as_dbsync_osinfo()->os_display_version()->str()
                                                          : "";
                            m_osData.sysName = delta->data_as_dbsync_osinfo()->sysname()
                                                   ? delta->data_as_dbsync_osinfo()->sysname()->str()
                                                   : "";
                            m_osData.kernelRelease = delta->data_as_dbsync_osinfo()->release()
                                                         ? delta->data_as_dbsync_osinfo()->release()->str()
                                                         : "";
                            m_osData.kernelVersion = delta->data_as_dbsync_osinfo()->version()
                                                         ? delta->data_as_dbsync_osinfo()->version()->str()
                                                         : "";

                            m_osData.hostName = delta->data_as_dbsync_osinfo()->hostname()
                                                    ? delta->data_as_dbsync_osinfo()->hostname()->str()
                                                    : "";
                            buildCPEName();

                            TOsDataCache::instance().setOsData(agentId().data(), m_osData);
                        }
                        else if (delta->data_type() == SyscollectorDeltas::Provider_dbsync_hotfixes)
                        {
                            // Set the affected component type
                            m_affectedComponentType = AffectedComponentType::Hotfix;

                            if (delta->operation()->str().compare("INSERTED") == 0)
                            {
                                m_type = ScannerType::HotfixInsert;

                                // Insert the new hotfix into the remediation data cache.
                                const std::string hotfix = delta->data_as_dbsync_hotfixes()->hotfix()->str();
                                Remediation remediation = {.hotfixes = {hotfix}};
                                TRemediationDataCache::instance().addRemediationData(agentId().data(),
                                                                                     std::move(remediation));
                            }
                            else if (delta->operation()->str().compare("DELETED") == 0)
                            {
                                m_type = ScannerType::HotfixDelete;
                            }

                            // If data comes from Wdb, we build the CPE and update the cache
                            if (!TOsDataCache::instance().getOsData(agentId().data(), m_osData))
                            {
                                buildCPEName();
                                TOsDataCache::instance().setOsData(agentId().data(), m_osData);
                            }
                        }
                    }
                    else
                    {
                        throw std::runtime_error("Operation not found in delta.");
                    }
                }
                else if constexpr (std::is_same_v<T, const Synchronization::SyncMsg*>)
                {
                    m_data = arg;
                    m_messageType = MessageType::Sync;
                    auto syncMsg = std::get<const Synchronization::SyncMsg*>(m_data);
                    if (syncMsg->data_type() == Synchronization::DataUnion_state)
                    {
                        if (syncMsg->data_as_state()->attributes_type() ==
                            Synchronization::AttributesUnion_syscollector_osinfo)
                        {
                            m_type = ScannerType::Os;

                            // Set the affected component type
                            m_affectedComponentType = AffectedComponentType::Os;

                            m_osData.architecture =
                                syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->architecture()
                                    ? syncMsg->data_as_state()
                                          ->attributes_as_syscollector_osinfo()
                                          ->architecture()
                                          ->str()
                                    : "";
                            m_osData.name =
                                syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_name()
                                    ? syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_name()->str()
                                    : "";
                            m_osData.version =
                                syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_version()
                                    ? syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_version()->str()
                                    : "";
                            m_osData.codeName =
                                syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_codename()
                                    ? syncMsg->data_as_state()
                                          ->attributes_as_syscollector_osinfo()
                                          ->os_codename()
                                          ->str()
                                    : "";
                            m_osData.majorVersion =
                                syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_major()
                                    ? syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_major()->str()
                                    : "";
                            m_osData.minorVersion =
                                syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_minor()
                                    ? syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_minor()->str()
                                    : "";
                            m_osData.patch =
                                syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_patch()
                                    ? syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_patch()->str()
                                    : "";
                            m_osData.platform =
                                syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_platform()
                                    ? syncMsg->data_as_state()
                                          ->attributes_as_syscollector_osinfo()
                                          ->os_platform()
                                          ->str()
                                    : "";
                            m_osData.sysName =
                                syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->sysname()
                                    ? syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->sysname()->str()
                                    : "";
                            m_osData.kernelRelease =
                                syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->release()
                                    ? syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->release()->str()
                                    : "";
                            m_osData.kernelVersion =
                                syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->version()
                                    ? syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->version()->str()
                                    : "";
                            m_osData.release =
                                syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_release()
                                    ? syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_release()->str()
                                    : "";
                            m_osData.build =
                                syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_build()
                                    ? syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_build()->str()
                                    : "";
                            m_osData.displayVersion =
                                syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->os_display_version()
                                    ? syncMsg->data_as_state()
                                          ->attributes_as_syscollector_osinfo()
                                          ->os_display_version()
                                          ->str()
                                    : "";
                            m_osData.hostName =
                                syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->hostname()
                                    ? syncMsg->data_as_state()->attributes_as_syscollector_osinfo()->hostname()->str()
                                    : "";

                            buildCPEName();
                            TOsDataCache::instance().setOsData(agentId().data(), m_osData);
                        }
                        else if (syncMsg->data_as_state()->attributes_type() ==
                                 Synchronization::AttributesUnion_syscollector_packages)
                        {
                            m_type = ScannerType::PackageInsert;
                            // Set the affected component type
                            m_affectedComponentType = AffectedComponentType::Package;

                            // If data comes from Wdb, we build the CPE and update the cache
                            if (!TOsDataCache::instance().getOsData(agentId().data(), m_osData))
                            {
                                buildCPEName();
                                TOsDataCache::instance().setOsData(agentId().data(), m_osData);
                            }
                        }
                        else if (syncMsg->data_as_state()->attributes_type() ==
                                 Synchronization::AttributesUnion_syscollector_hotfixes)
                        {
                            m_type = ScannerType::HotfixInsert;
                            // Set the affected component type
                            m_affectedComponentType = AffectedComponentType::Hotfix;

                            // Insert the new hotfix into the remediation data cache.
                            const std::string hotfix =
                                syncMsg->data_as_state()->attributes_as_syscollector_hotfixes()->hotfix()->str();
                            Remediation remediation = {.hotfixes = {hotfix}};
                            TRemediationDataCache::instance().addRemediationData(agentId().data(),
                                                                                 std::move(remediation));

                            // If data comes from Wdb, we build the CPE and update the cache
                            if (!TOsDataCache::instance().getOsData(agentId().data(), m_osData))
                            {
                                buildCPEName();
                                TOsDataCache::instance().setOsData(agentId().data(), m_osData);
                            }
                        }
                    }
                    else if (syncMsg->data_type() == Synchronization::DataUnion_integrity_clear)
                    {
                        if (syncMsg->data_as_integrity_clear()->attributes_type()->str().compare(
                                "syscollector_packages") == 0)

                        {
                            m_type = ScannerType::IntegrityClear;
                            // Set the affected component type
                            m_affectedComponentType = AffectedComponentType::Package;
                        }
                        else if (syncMsg->data_as_integrity_clear()->attributes_type()->str().compare(
                                     "syscollector_osinfo") == 0)
                        {
                            m_type = ScannerType::IntegrityClear;
                            // Set the affected component type
                            m_affectedComponentType = AffectedComponentType::Os;
                        }
                        else
                        {
                            // Integrity clear for othre components not affected by the scanner.
                        }
                    }
                    else if (syncMsg->data_type() == Synchronization::DataUnion_integrity_check_global)
                    {
                        if (syncMsg->data_as_integrity_check_global()->attributes_type()->str().compare(
                                "syscollector_packages") == 0 ||
                            syncMsg->data_as_integrity_check_global()->attributes_type()->str().compare(
                                "syscollector_osinfo") == 0)
                        {
                            m_type = ScannerType::GlobalSyncInventory;
                            m_affectedComponentType = AffectedComponentType::Agent;
                        }
                    }
                }
                else if constexpr (std::is_same_v<T, const nlohmann::json*>)
                {
                    m_data = arg;
                    auto message = std::get<const nlohmann::json*>(m_data);

                    // There are two types of JSON messages, one is an array and the other is an object.
                    // The object type always contains an action field, which is used to determine the type of scan.
                    if (message->is_object())
                    {
                        const auto actionValue = message->at("action");

                        // This is used to trigger a re-scan of all agents, used if the module change from disabled to
                        // enabled.
                        if (actionValue == "reboot")
                        {
                            m_type = ScannerType::ReScanAllAgents;
                            m_messageType = MessageType::ActionTrigger;
                            // Set the affected component type
                            m_affectedComponentType = AffectedComponentType::Agent;
                        }
                        // This is used to cleanup all data on the local inventory and the indexer data.
                        else if (actionValue == "cleanup")
                        {
                            m_type = ScannerType::CleanupAllAgentData;
                            m_messageType = MessageType::ActionTrigger;
                            // Set the affected component type
                            m_affectedComponentType = AffectedComponentType::Agent;
                        }
                        // This is used to trigger a delete and re-scan for a single agent.
                        else if (actionValue == "scanAgent")
                        {
                            m_type = ScannerType::ReScanSingleAgent;
                            m_messageType = MessageType::DataJSON;
                            // Set the affected component type
                            m_affectedComponentType = AffectedComponentType::Agent;
                        }
                        // This is used if a database update message is received.
                        // It handles specific upgrades scenarios.
                        else if (actionValue == "upgradeAgentDB")
                        {
                            m_messageType = MessageType::DataJSON;
                            m_type = ScannerType::Unknown;
                            m_affectedComponentType = AffectedComponentType::Agent;

                            int newDBVersion = message->at("/data/new_db_version"_json_pointer).get<int>();

                            switch (newDBVersion)
                            {
                                // Global queries. The agents re-sync all data.
                                case WazuhDBUpgradeSchemaVersion::V15:
                                    m_type = ScannerType::CleanupSingleAgentData;
                                    m_affectedComponentType = AffectedComponentType::Agent;
                                    break;
                                default: break;
                            }
                        }
                        // Used for the RSync deleted events from Wazuh-DB
                        else if (actionValue == "deletePackage")
                        {
                            m_type = ScannerType::PackageDelete;
                            m_messageType = MessageType::DataJSON;
                            // Set the affected component type
                            m_affectedComponentType = AffectedComponentType::Package;
                        }
                        // Used for the RSync deleted events from Wazuh-DB
                        else if (actionValue == "deleteHotfix")
                        {
                            m_type = ScannerType::HotfixDelete;
                            m_messageType = MessageType::DataJSON;
                            // Set the affected component type
                            m_affectedComponentType = AffectedComponentType::Hotfix;
                        }
                        // This is used to trigger a delete of all data for a single agent, used if a agent is removed.
                        else if (actionValue == "deleteAgent")
                        {
                            m_type = ScannerType::CleanupSingleAgentData;
                            m_messageType = MessageType::DataJSON;
                            // Set the affected component type
                            m_affectedComponentType = AffectedComponentType::Agent;
                        }
                        else
                        {
                            throw std::runtime_error("Unable to build scan context. Unknown action");
                        }

                        m_noIndex = message->contains("no-index") ? message->at("no-index").get<bool>() : false;
                    }
                    else
                    {
                        throw std::runtime_error("Unable to build scan context. Unknown JSON format");
                    }
                }
                else
                {
                    throw std::runtime_error("Unable to build scan context. Unknown type");
                }
            },
            data);
    }

    // LCOV_EXCL_START
    /**
     * @brief Class destructor.
     *
     */
    ~TScanContext() = default;
    // LCOV_EXCL_STOP

    /**
     * @brief Gets scan type.
     *
     * @return Scan type.
     */
    ScannerType getType() const
    {
        return m_type;
    }

    /**
     * @brief Getter for messages.
     *
     * @return const nlohmann::json& The shared pointer to the JSON object.
     */
    const nlohmann::json& getMessages() const
    {
        return *std::get<const nlohmann::json*>(m_data);
    }

    /**
     * @brief Gets package name.
     * @return Package name.
     */
    std::string_view packageName() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->data_as_dbsync_packages() == nullptr)
                {
                    return "";
                }
                return delta->data_as_dbsync_packages()->name() ? delta->data_as_dbsync_packages()->name()->c_str()
                                                                : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->data_as_state() == nullptr ||
                    syncMsg->data_as_state()->attributes_as_syscollector_packages() == nullptr)
                {
                    return "";
                }
                return syncMsg->data_as_state()->attributes_as_syscollector_packages()->name()
                           ? syncMsg->data_as_state()->attributes_as_syscollector_packages()->name()->c_str()
                           : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/data/name"_json_pointer)
                           ? jsonData->at("/data/name"_json_pointer).get_ref<const std::string&>().c_str()
                           : "";
            });
    }

    /**
     * @brief Gets package version.
     * @return Package version.
     */
    std::string_view packageVersion() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->data_as_dbsync_packages() == nullptr)
                {
                    return "";
                }
                return delta->data_as_dbsync_packages()->version()
                           ? delta->data_as_dbsync_packages()->version()->c_str()
                           : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->data_as_state() == nullptr ||
                    syncMsg->data_as_state()->attributes_as_syscollector_packages() == nullptr)
                {
                    return "";
                }
                return syncMsg->data_as_state()->attributes_as_syscollector_packages()->version()
                           ? syncMsg->data_as_state()->attributes_as_syscollector_packages()->version()->c_str()
                           : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/data/version"_json_pointer)
                           ? jsonData->at("/data/version"_json_pointer).get_ref<const std::string&>().c_str()
                           : "";
            });
    }

    /**
     * @brief Gets vendor name.
     * @return Vendor name.
     */
    std::string_view packageVendor() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->data_as_dbsync_packages() == nullptr)
                {
                    return "";
                }
                return delta->data_as_dbsync_packages()->vendor() ? delta->data_as_dbsync_packages()->vendor()->c_str()
                                                                  : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->data_as_state() == nullptr ||
                    syncMsg->data_as_state()->attributes_as_syscollector_packages() == nullptr)
                {
                    return "";
                }
                return syncMsg->data_as_state()->attributes_as_syscollector_packages()->vendor()
                           ? syncMsg->data_as_state()->attributes_as_syscollector_packages()->vendor()->c_str()
                           : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/data/vendor"_json_pointer)
                           ? jsonData->at("/data/vendor"_json_pointer).get_ref<const std::string&>().c_str()
                           : "";
            });
    }

    /**
     * @brief Gets package install time.
     * @return Package install time.
     */
    std::string_view packageInstallTime() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->data_as_dbsync_packages() == nullptr)
                {
                    return "";
                }
                return delta->data_as_dbsync_packages()->install_time()
                           ? delta->data_as_dbsync_packages()->install_time()->c_str()
                           : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->data_as_state() == nullptr ||
                    syncMsg->data_as_state()->attributes_as_syscollector_packages() == nullptr)
                {
                    return "";
                }
                return syncMsg->data_as_state()->attributes_as_syscollector_packages()->install_time()
                           ? syncMsg->data_as_state()->attributes_as_syscollector_packages()->install_time()->c_str()
                           : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/data/install_time"_json_pointer)
                           ? jsonData->at("/data/install_time"_json_pointer).get_ref<const std::string&>().c_str()
                           : "";
            });
    }

    /**
     * @brief Gets package location.
     * @return Package location.
     */
    std::string_view packageLocation() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->data_as_dbsync_packages() == nullptr)
                {
                    return "";
                }
                return delta->data_as_dbsync_packages()->location()
                           ? delta->data_as_dbsync_packages()->location()->c_str()
                           : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->data_as_state() == nullptr ||
                    syncMsg->data_as_state()->attributes_as_syscollector_packages() == nullptr)
                {
                    return "";
                }
                return syncMsg->data_as_state()->attributes_as_syscollector_packages()->location()
                           ? syncMsg->data_as_state()->attributes_as_syscollector_packages()->location()->c_str()
                           : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/data/location"_json_pointer)
                           ? jsonData->at("/data/location"_json_pointer).get_ref<const std::string&>().c_str()
                           : "";
            });
    }

    /**
     * @brief Gets package architecture.
     * @return Package architecture.
     */
    std::string_view packageArchitecture() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->data_as_dbsync_packages() == nullptr)
                {
                    return "";
                }
                return delta->data_as_dbsync_packages()->architecture()
                           ? delta->data_as_dbsync_packages()->architecture()->c_str()
                           : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->data_as_state() == nullptr ||
                    syncMsg->data_as_state()->attributes_as_syscollector_packages() == nullptr)
                {
                    return "";
                }
                return syncMsg->data_as_state()->attributes_as_syscollector_packages()->architecture()
                           ? syncMsg->data_as_state()->attributes_as_syscollector_packages()->architecture()->c_str()
                           : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/data/architecture"_json_pointer)
                           ? jsonData->at("/data/architecture"_json_pointer).get_ref<const std::string&>().c_str()
                           : "";
            });
    }

    /**
     * @brief Gets package groups.
     * @return Package groups.
     */
    std::string_view packageGroups() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->data_as_dbsync_packages() == nullptr)
                {
                    return "";
                }
                return delta->data_as_dbsync_packages()->groups() ? delta->data_as_dbsync_packages()->groups()->c_str()
                                                                  : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->data_as_state() == nullptr ||
                    syncMsg->data_as_state()->attributes_as_syscollector_packages() == nullptr)
                {
                    return "";
                }
                return syncMsg->data_as_state()->attributes_as_syscollector_packages()->groups()
                           ? syncMsg->data_as_state()->attributes_as_syscollector_packages()->groups()->c_str()
                           : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/data/groups"_json_pointer)
                           ? jsonData->at("/data/groups"_json_pointer).get_ref<const std::string&>().c_str()
                           : "";
            });
    }

    /**
     * @brief Gets package description
     * @return Package description.
     */
    std::string_view packageDescription() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->data_as_dbsync_packages() == nullptr)
                {
                    return "";
                }
                return delta->data_as_dbsync_packages()->description()
                           ? delta->data_as_dbsync_packages()->description()->c_str()
                           : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->data_as_state() == nullptr ||
                    syncMsg->data_as_state()->attributes_as_syscollector_packages() == nullptr)
                {
                    return "";
                }
                return syncMsg->data_as_state()->attributes_as_syscollector_packages()->description()
                           ? syncMsg->data_as_state()->attributes_as_syscollector_packages()->description()->c_str()
                           : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/data/description"_json_pointer)
                           ? jsonData->at("/data/description"_json_pointer).get_ref<const std::string&>().c_str()
                           : "";
            });
    }

    /**
     * @brief Gets package size.
     * @return Package size.
     */
    int64_t packageSize() const
    {
        return extractData<int64_t>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->data_as_dbsync_packages() == nullptr)
                {
                    return 0L;
                }
                return delta->data_as_dbsync_packages()->size();
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->data_as_state() == nullptr ||
                    syncMsg->data_as_state()->attributes_as_syscollector_packages() == nullptr)
                {
                    return 0L;
                }
                return syncMsg->data_as_state()->attributes_as_syscollector_packages()->size();
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/data/size"_json_pointer)
                           ? jsonData->at("/data/size"_json_pointer).get<int64_t>()
                           : 0L;
            });
    }

    /**
     * @brief Gets package priority.
     * @return Package priority.
     */
    std::string_view packagePriority() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->data_as_dbsync_packages() == nullptr)
                {
                    return "";
                }
                return delta->data_as_dbsync_packages()->priority()
                           ? delta->data_as_dbsync_packages()->priority()->c_str()
                           : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->data_as_state() == nullptr ||
                    syncMsg->data_as_state()->attributes_as_syscollector_packages() == nullptr)
                {
                    return "";
                }
                return syncMsg->data_as_state()->attributes_as_syscollector_packages()->priority()
                           ? syncMsg->data_as_state()->attributes_as_syscollector_packages()->priority()->c_str()
                           : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/data/priority"_json_pointer)
                           ? jsonData->at("/data/priority"_json_pointer).get_ref<const std::string&>().c_str()
                           : "";
            });
    }

    /**
     * @brief Gets package multi arch.
     * @return Package multi arch.
     */
    std::string_view packageMultiarch() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->data_as_dbsync_packages() == nullptr)
                {
                    return "";
                }
                return delta->data_as_dbsync_packages()->multiarch()
                           ? delta->data_as_dbsync_packages()->multiarch()->c_str()
                           : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->data_as_state() == nullptr ||
                    syncMsg->data_as_state()->attributes_as_syscollector_packages() == nullptr)
                {
                    return "";
                }
                return syncMsg->data_as_state()->attributes_as_syscollector_packages()->multiarch()
                           ? syncMsg->data_as_state()->attributes_as_syscollector_packages()->multiarch()->c_str()
                           : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/data/multiarch"_json_pointer)
                           ? jsonData->at("/data/multiarch"_json_pointer).get_ref<const std::string&>().c_str()
                           : "";
            });
    }

    /**
     * @brief Gets package source
     * @return Package source.
     */
    std::string_view packageSource() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->data_as_dbsync_packages() == nullptr)
                {
                    return "";
                }
                return delta->data_as_dbsync_packages()->source() ? delta->data_as_dbsync_packages()->source()->c_str()
                                                                  : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->data_as_state() == nullptr ||
                    syncMsg->data_as_state()->attributes_as_syscollector_packages() == nullptr)
                {
                    return "";
                }
                return syncMsg->data_as_state()->attributes_as_syscollector_packages()->source()
                           ? syncMsg->data_as_state()->attributes_as_syscollector_packages()->source()->c_str()
                           : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/data/source"_json_pointer)
                           ? jsonData->at("/data/source"_json_pointer).get_ref<const std::string&>().c_str()
                           : "";
            });
    }

    /**
     * @brief Gets package format.
     * @return Package format.
     */
    std::string_view packageFormat() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->data_as_dbsync_packages() == nullptr)
                {
                    return "";
                }
                return delta->data_as_dbsync_packages()->format() ? delta->data_as_dbsync_packages()->format()->c_str()
                                                                  : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->data_as_state() == nullptr ||
                    syncMsg->data_as_state()->attributes_as_syscollector_packages() == nullptr)
                {
                    return "";
                }
                return syncMsg->data_as_state()->attributes_as_syscollector_packages()->format()
                           ? syncMsg->data_as_state()->attributes_as_syscollector_packages()->format()->c_str()
                           : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/data/format"_json_pointer)
                           ? jsonData->at("/data/format"_json_pointer).get_ref<const std::string&>().c_str()
                           : "";
            });
    }

    /**
     * @brief Gets package id.
     * @return Package id.
     */
    std::string_view packageItemId() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->data_as_dbsync_packages() == nullptr)
                {
                    return "";
                }
                return delta->data_as_dbsync_packages()->item_id()
                           ? delta->data_as_dbsync_packages()->item_id()->c_str()
                           : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->data_as_state() == nullptr ||
                    syncMsg->data_as_state()->attributes_as_syscollector_packages() == nullptr)
                {
                    return "";
                }
                return syncMsg->data_as_state()->attributes_as_syscollector_packages()->item_id()
                           ? syncMsg->data_as_state()->attributes_as_syscollector_packages()->item_id()->c_str()
                           : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/data/item_id"_json_pointer)
                           ? jsonData->at("/data/item_id"_json_pointer).get_ref<const std::string&>().c_str()
                           : "";
            });
    }

    /**
     * @brief Gets agent id.
     * @return Agent id.
     */
    std::string_view agentId() const
    {
        if (m_agentId.empty())
        {

            auto result = extractData<std::string_view>(
                [](const SyscollectorDeltas::Delta* delta) -> std::string_view
                {
                    if (delta && delta->agent_info() && delta->agent_info()->agent_id())
                    {
                        return delta->agent_info()->agent_id()->c_str();
                    }
                    return "";
                },
                [](const Synchronization::SyncMsg* syncMsg) -> std::string_view
                {
                    if (syncMsg && syncMsg->agent_info() && syncMsg->agent_info()->agent_id())
                    {
                        return syncMsg->agent_info()->agent_id()->c_str();
                    }
                    return "";
                },
                [](const nlohmann::json* jsonData) -> std::string_view
                {
                    if (jsonData && jsonData->contains("/agent_info/agent_id"_json_pointer))
                    {
                        return jsonData->at("/agent_info/agent_id"_json_pointer).get_ref<const std::string&>();
                    }
                    return "";
                });

            // Use padString based on result
            m_agentId = Utils::padString(result.empty() ? "" : result.data(), '0', 3);
        }

        return m_agentId;
    }

    /**
     * @brief Gets agent IP.
     *
     * @return Agent IP.
     */
    std::string_view agentIp() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->agent_info() == nullptr)
                {
                    return "";
                }
                return delta->agent_info()->agent_ip() ? delta->agent_info()->agent_ip()->c_str() : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->agent_info() == nullptr)
                {
                    return "";
                }
                return syncMsg->agent_info()->agent_ip() ? syncMsg->agent_info()->agent_ip()->c_str() : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/agent_info/agent_ip"_json_pointer)
                           ? jsonData->at("/agent_info/agent_ip"_json_pointer).get_ref<const std::string&>().c_str()
                           : "";
            });
    }

    /**
     * @brief Gets agent name.
     *
     * @return Agent name.
     */
    std::string_view agentName() const
    {
        if (agentId() == "000")
        {
            return TGlobalData::instance().managerName();
        }

        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->agent_info() == nullptr)
                {
                    return "";
                }
                return delta->agent_info()->agent_name() ? delta->agent_info()->agent_name()->c_str() : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->agent_info() == nullptr)
                {
                    return "";
                }
                return syncMsg->agent_info()->agent_name() ? syncMsg->agent_info()->agent_name()->c_str() : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/agent_info/agent_name"_json_pointer)
                           ? jsonData->at("/agent_info/agent_name"_json_pointer).get_ref<const std::string&>().c_str()
                           : "";
            });
    }

    /**
     * @brief Gets agent version.
     *
     * @return Agent version.
     */
    std::string_view agentVersion() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->agent_info() == nullptr)
                {
                    return "";
                }
                return delta->agent_info()->agent_version() ? delta->agent_info()->agent_version()->c_str() : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->agent_info() == nullptr)
                {
                    return "";
                }
                return syncMsg->agent_info()->agent_version() ? syncMsg->agent_info()->agent_version()->c_str() : "";
            },
            [](const nlohmann::json* jsonData)
            {
                return jsonData->contains("/agent_info/agent_version"_json_pointer)
                           ? jsonData->at("/agent_info/agent_version"_json_pointer)
                                 .get_ref<const std::string&>()
                                 .c_str()
                           : "";
            });
    }

    /**
     * @brief Gets os hostName.
     * @return Os hostName.
     */
    std::string_view osHostName() const
    {
        return m_osData.hostName;
    }

    /**
     * @brief Gets os architecture.
     * @return Os architecture.
     */
    std::string_view osArchitecture() const
    {
        return m_osData.architecture;
    }

    /**
     * @brief Gets os name.
     * @return Os name.
     */
    std::string_view osName() const
    {
        return m_osData.name;
    }

    /**
     * @brief Gets os version.
     * @return Os version.
     */
    std::string_view osVersion() const
    {
        return m_osData.version;
    }

    /**
     * @brief Gets os codeName.
     * @return Os codeName.
     */
    std::string_view osCodeName() const
    {
        return m_osData.codeName;
    }

    /**
     * @brief Gets os major version.
     * @return Os major version.
     */
    std::string_view osMajorVersion() const
    {
        return m_osData.majorVersion;
    }

    /**
     * @brief Gets os minor version.
     * @return Os minor version.
     */
    std::string_view osMinorVersion() const
    {
        return m_osData.minorVersion;
    }

    /**
     * @brief Gets os patch version.
     * @return Os patch version.
     */
    std::string_view osPatch() const
    {
        return m_osData.patch;
    }

    /**
     * @brief Gets os build number.
     * @return Os build number.
     */
    std::string_view osBuild() const
    {
        return m_osData.build;
    }

    /**
     * @brief Gets os platform.
     * @return Os platform.
     */
    std::string_view osPlatform() const
    {
        return m_osData.platform;
    }

    /**
     * @brief Gets os kernel sysName.
     * @return Os kernel sysName.
     */
    std::string_view osKernelSysName() const
    {
        return m_osData.sysName;
    }

    /**
     * @brief Gets os kernel release.
     * @return Os kernel release.
     */
    std::string_view osKernelRelease() const
    {
        return m_osData.kernelRelease;
    }

    /**
     * @brief Gets os kernel version.
     * @return Os kernel version.
     */
    std::string_view osKernelVersion() const
    {
        return m_osData.kernelVersion;
    }

    /**
     * @brief Gets os release
     * @return Os release.
     */
    std::string_view osRelease() const
    {
        return m_osData.release;
    }

    /**
     * @brief Gets os display name.
     * @return Os display name.
     */
    std::string_view osDisplayVersion() const
    {
        return m_osData.displayVersion;
    }

    /**
     * @brief Get cluster name.
     * @return Cluster name.
     */
    std::string_view clusterName() const
    {
        static std::string clusterName = PolicyManager::instance().getClusterName();
        return clusterName;
    }

    /**
     * @brief Gets cluster node name
     * @return Cluster node name.
     */
    std::string_view clusterNodeName() const
    {
        static std::string clusterNodeName = PolicyManager::instance().getClusterNodeName();
        return clusterNodeName;
    }

    /**
     * @brief Gets cluster status.
     * @return Cluster node status.
     */
    bool clusterStatus() const
    {
        static bool clusterStatus = PolicyManager::instance().getClusterStatus();
        return clusterStatus;
    }

    /**
     * @brief Gets OS CPE.
     * @return OS CPE.
     */
    std::string_view osCPEName() const
    {
        return m_osData.cpeName;
    }

    /**
     * @brief get the hotfix identifier being installed in the current scan.
     *
     * @details If no hotfix is being installed, an empty string is returned.
     *
     * @return std::string_view hotfix identifier.
     */
    std::string_view hotfixId() const
    {
        return extractData<std::string_view>(
            [](const SyscollectorDeltas::Delta* delta)
            {
                if (delta->data_as_dbsync_hotfixes() == nullptr)
                {
                    return "";
                }
                return delta->data_as_dbsync_hotfixes()->hotfix() ? delta->data_as_dbsync_hotfixes()->hotfix()->c_str()
                                                                  : "";
            },
            [](const Synchronization::SyncMsg* syncMsg)
            {
                if (syncMsg->data_as_state() == nullptr ||
                    syncMsg->data_as_state()->attributes_as_syscollector_hotfixes() == nullptr)
                {
                    return "";
                }
                return syncMsg->data_as_state()->attributes_as_syscollector_hotfixes()->hotfix()
                           ? syncMsg->data_as_state()->attributes_as_syscollector_hotfixes()->hotfix()->c_str()
                           : "";
            },
            []([[maybe_unused]] const nlohmann::json* jsonData) { return ""; });
    }

    /**
     * @brief Gets manager name.
     * @return Manager name.
     */
    std::string_view managerName() const
    {
        return TGlobalData::instance().managerName();
    }

    /**
     * @brief Gets the message type.
     *
     * @return MessageType The type of message of the context.
     */
    MessageType messageType() const
    {
        return m_messageType;
    }

    /**
     * @brief Feed source information.
     *
     * @note Use @see VulnerabilitySource enum to access each field
     *
     * @return Pair with CNA/ADP base name and CNA/ADP expanded name.
     */
    std::pair<std::string, std::string> m_vulnerabilitySource;

    /**
     * @brief Gets the affected component type.
     *
     * @return AffectedComponentType The type of component that is affected in the event.
     */
    AffectedComponentType affectedComponentType() const
    {
        return m_affectedComponentType;
    }

    /**
     * @brief Elements to process.
     */
    std::unordered_map<std::string, nlohmann::json> m_elements;

    /**
     * @brief Elements for alerts.
     *
     */
    std::unordered_map<std::string, nlohmann::json> m_alerts;

    /**
     * @brief Elements matching the query.
     *
     */
    std::unordered_map<std::string, MatchCondition> m_matchConditions;

    /**
     * @brief Detection source for CVEs only when the default CNA is used.
     *
     */
    std::unordered_map<std::string, std::string> m_cnaDetectionSource;

    /**
     * @brief Agent data list.
     *
     * @details This list is used to store the agent data for the re-scan all agents event.
     */
    std::vector<AgentData> m_agents;

    /**
     * @brief Agent data list with exceptions.
     *
     * @details This list is used to store the agent data with exceptions during the re-scan all agents event.
     */
    std::vector<AgentData> m_agentsWithIncompletedScan;

    /**
     * @brief Variable to store if the inventory is empty before an integrity clear event for the agent.
     *
     */
    bool m_isInventoryEmpty = false;

    /**
     * @brief Variable to store if is the first scan for the agent.
     *
     */
    bool m_isFirstScan = true;

    /**
     * @brief Variable to check if the scan is a no-index scan.
     * @details This is used to avoid indexing the scan results.
     */
    bool m_noIndex = false;
    // LCOV_EXCL_STOP
private:
    /**
     * @brief Scan type.
     *
     */
    ScannerType m_type = ScannerType::Unknown;

    /**
     * @brief Message type.
     * @details Delta or Sync message.
     */
    MessageType m_messageType = MessageType::Unknown;

    /**
     * @brief Scan context.
     *
     */
    std::variant<const SyscollectorDeltas::Delta*, const Synchronization::SyncMsg*, const nlohmann::json*> m_data;

    /**
     * @brief Os data.
     *
     */
    Os m_osData {};

    /**
     * @brief Agent id.
     *
     */
    mutable std::string m_agentId;

    /**
     * @brief Element type to process.
     *
     */
    AffectedComponentType m_affectedComponentType = AffectedComponentType::Unknown;
};

using ScanContext = TScanContext<>;

#endif // _SCAN_CONTEXT_HPP
